﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.Reflection;

namespace Infrastructure.UI.Abstract
{
    /// <summary>
    /// BindingManager 实现绑定管理
    /// </summary>
    public abstract class AbstractBindingManager
    {
        public AbstractBindingManager()
        {

        }

        Hashtable bingdingCache = new Hashtable();

        #region Control Binding

        /// <summary>
        /// Binding
        /// </summary>
        /// <param name="control">
        /// 与对象属性邦定的控件，邦定属性根据邦定对象属性名有关
        /// 如控件名为txtPartnerCode,则将在邦定对象obj中查找PartnerCode 属性，若存在则建立邦定
        /// 不同控件的邦定,调用不同控件Binding 重载函数.
        /// </param>
        /// <param name="control">用户控件</param>
        /// <param name="obj">邦定对象,若对象为空,则清除Control显示数据,并置控件为不可编辑状态</param>
        /// <param name="enabled">
        /// false，则不允许进行编辑；
        /// true,允许编辑</param>
        public void Binding(Control control, object obj, bool enabled)
        {
            if (control.Name.Length <= 3 || obj == null) return;

            string propertyname = control.Name.Substring(3);
            System.Reflection.PropertyInfo property = obj.GetType().GetProperty(propertyname);
            bool hasDone = false;
            if (property != null)
            {
                if (this.bingdingCache.ContainsKey(control))
                {
                    this.bingdingCache.Remove(control);
                }
                control.DataBindings.Clear();
                hasDone = ActualBinding(control, property, obj);
            }
            if (!hasDone && control.Controls != null)
            {
                foreach (Control childcontrol in control.Controls)
                    Binding(childcontrol, obj, enabled);
            }
        }

        /// <summary>
        /// Actuals the binding.
        /// </summary>
        /// <param name="control">The control.</param>
        /// <returns></returns>
        public virtual bool ActualBinding(Control control, PropertyInfo property, Object obj)
        {
            return false;
        }

        protected Binding DoBinding(Control control, string propertyName, object obj, PropertyInfo property)
        {
            System.Windows.Forms.Binding binding = new Binding(propertyName, obj, property.Name);

            control.DataBindings.Add(binding);
            if (this.bingdingCache.Contains(control))
                this.bingdingCache.Remove(control);

            this.bingdingCache.Add(control, binding);

            return binding;
        }

        public virtual void ClearBinding()
        {
            foreach (var cache in this.bingdingCache.Keys)
            {
                Control ctl = cache as Control;
                if (ctl == null) continue;
                ctl.DataBindings.Clear();
            }
            this.bingdingCache.Clear();
        }
        #endregion

        #region EndCurrentEdit
        /// <summary>
        /// 结束当前编辑
        /// </summary>
        /// <param name="ctrl"></param>
        public void EndCurrentEdit(Control ctrl)
        {
            if (ctrl == null) return;

            if (this.bingdingCache != null && this.bingdingCache.Contains(ctrl))
            {
                Binding binding = (Binding)this.bingdingCache[ctrl];

                //控件邦定DataSource 不为空时,将控件显示值更新到邦定数据
                if (binding.DataSource != null && binding.BindingManagerBase != null)
                    binding.BindingManagerBase.EndCurrentEdit();
            }
        }

        /// <summary>
        /// 结束当前编辑
        /// </summary>
        public void EndCurrentEdit()
        {
            if (this.bingdingCache != null)
            {
                IDictionaryEnumerator enumetor = this.bingdingCache.GetEnumerator();
                while (enumetor.MoveNext())
                {
                    Binding binding = (Binding)enumetor.Value;

                    //控件邦定DataSource 不为空时,将控件显示值更新到邦定数据
                    if (binding.DataSource != null && binding.BindingManagerBase != null)
                        binding.BindingManagerBase.EndCurrentEdit();
                }
            }
        }
        #endregion

        #region OnBindingParse

        /// <summary>
        /// 处理邦定对象=null处理,主要针对System.Windows.Froms文本型编辑控件,如TextBox/ComboBox/RichTextBox等.
        /// 当控件值为String.Empty,则设置邦定对象值为空.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnBindingParse(object sender, ConvertEventArgs e)
        {
            if (e.Value == System.DBNull.Value)
                e.Value = null;
        }
        #endregion

        #region OnBindingFormat
        /// <summary>
        /// 处理邦定对象=null处理,主要针对System.Windows.Froms文本型编辑控件,如TextBox/ComboBox/RichTextBox等.
        /// 当邦定对象为空,则设置控件值为String.Empty
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnBindingFormat(object sender, ConvertEventArgs e)
        {
            if (e.Value == null)
            {
                e.Value = System.DBNull.Value;
            }
        }
        #endregion

        #region OnEditValueChanged
        /// <summary>
        /// 邦定控件数据值发生改变时事件处理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnEditValueChanged(object sender, EventArgs e)
        {
            try
            {
                if (!((Control)sender).Focused && ((Control)sender).DataBindings.Count > 0)
                {
                    foreach (Binding binding in ((Control)sender).DataBindings)
                    {
                        //控件邦定DataSource 不为空时,又控件显示值更新到邦定数据
                        if (binding.DataSource != null && binding.BindingManagerBase != null)
                        {
                            //EndEdit(binding);
                            binding.BindingManagerBase.EndCurrentEdit();
                        }
                    }
                }

            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        #region Convert

        /// <summary>
        /// 类型转换
        /// </summary>
        /// <param name="targetType">目标类型</param>
        /// <param name="value">源对象</param>
        /// <returns></returns>
        public object Convert(Type targetType, object value)
        {
            if (System.Convert.IsDBNull(value)) return null;
            return System.Convert.ChangeType(value, targetType);
        }
        #endregion

        protected void EndEdit(Binding binding)
        {
            if (binding == null ||
                binding.Control == null ||
                binding.DataSource == null ||
                binding.BindingMemberInfo.BindingMember == null ||
                binding.PropertyName == null)
                return;
            object val = binding.Control.GetType().GetProperty(binding.PropertyName).GetValue(binding.Control, null);
            System.Reflection.PropertyInfo property = binding.DataSource.GetType().GetProperty(binding.BindingMemberInfo.BindingMember);
            val = this.Convert(property.PropertyType, val);
            property.SetValue(binding.DataSource, val, null);
        }
        #endregion
    }
}
